fix: correct APP_NAME and persistent data paths for deployed apps - #143
Merged
Conversation
Every compose file (apps/common.yml's shared services, plus traefik's
own volume mount) references \${APP_NAME}, but nothing in the deploy
pipeline ever wrote it - vault manifests only carry an app's actual
secrets, never its own name. Docker Compose auto-loads .env from its
own working directory, so on the target host \${APP_NAME} silently
resolved to an empty string for every app.
This was invisible until the first real deploy (to heimdall): rybbit's
env_file: ./\${APP_NAME}/.env resolved to apps/.env (no such file,
hard failure), and traefik's ../../apps-data/\${APP_NAME}:/letsencrypt
silently mounted apps-data/ itself instead of apps-data/traefik/ -
wrong acme.json location, no error since the directory exists either
way. Both are fixed by prepending APP_NAME={app} to each app's
resolved .env on the runner, before it's pushed.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
apps-data/${APP_NAME} (and postgres-*.yml, redis-*.yml, and every other
template/app using it) assumed apps/{app}/docker-compose.yml sits two
directories under the base path - true locally (repo_root/apps/{app}/),
false on a deployed host (base_path/current/apps/{app}/, with current
a symlink into releases/{timestamp}/). ../.. from apps/{app}/ only
escapes back to current/, not base_path/, so every one of these mounts
landed inside that release's own directory - exactly the acme.json bug
just fixed for traefik, but latent in every app with a data volume.
Fixed by never using a relative path for this at all: deploy_to_host
now appends DATA_DIR={base_path}/apps-data/{app} to each app's .env on
the host itself (computed per-host, since base_path depends on that
host's $HOME - unlike APP_NAME, this can't be baked into the release
tree, which is shared across every host a target deploys to). Every
compose file/template using apps-data now references ${DATA_DIR}
directly instead of ../../apps-data/${APP_NAME} or ../apps-data/${APP_NAME}.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two related bugs found while getting the first real deploy to heimdall working.
1.
APP_NAMEwas never written anywhere. Every compose file references${APP_NAME}, but nothing indeploy/deploy.pyever set it - vault manifests only carry an app's actual secrets, never its own name. Fixed by prependingAPP_NAME={app}to each app's resolved.envinresolve_app_envs.2.
apps-data/${APP_NAME}relative paths resolved to the wrong place on a deployed host.docker composeruns from{base_path}/current/apps/{app}/, wherecurrentis a symlink intoreleases/{timestamp}/.../../apps-data/${APP_NAME}(traefik) or../apps-data/${APP_NAME}(every db template - postgres, redis, mysql, mongodb, clickhouse, timescale, paradedb) only escapes back tocurrent/, not the true base path - so persistent data silently landed inside a specific release's own directory, not the persistentapps-data/sibling ofreleases/. Confirmed on heimdall: traefik's acme.json ended up at~/flightdeck/current/apps-data/acme.json(i.e.releases/{ts}/apps-data/acme.json) instead of the persistent~/flightdeck/apps-data/traefik/acme.json- it would have been silently deleted on the nextkeep_releasesrotation.Fixed by never using a relative path for this:
deploy_to_hostnow computesDATA_DIR={base_path}/apps-data/{app}per host (can't be baked into the release tree likeAPP_NAME, sincebase_pathdepends on that host's$HOME, resolved only after SSH-connecting, and a target'shosts:can list more than one) and appends it to each app's already-pushed.envon the host itself, beforedocker composeever runs. Every compose file/template usingapps-datanow references${DATA_DIR}directly.Test plan
deploy/tests/(48 tests, updated) passdocker compose configverified for every app in the catalog withAPP_NAME/DATA_DIRset